<?php

/**
 * Část skládačky ��stčástčástČ
 * @author Michal Hantl
 * @version 0.0.1
 */

class cPart {
	
	public $physic = true;
	
	/** pole childreních partů */
	public $chParts =  array();
	public $name = "part";

	public $node = null; 
	public $cms = null; 
	 
	/**
	 * překouše se definice a máme svou konfiguraci
	 * @donNode kus definice typu stránky = config
	 * @dbData data z DB  
	 */
	function __construct(simpleXMLElement $element, $parent) 
	{
		
		$this->parent = $parent;
		
		if ($parent->node===null) {
			$this->node = $parent;
		} else $this->node = $parent->node;
		
		$this->cms = $parent->cms;	
		
		// můj element
		$this->element = $element;
		

		if (($this->tagName = $this->getAttribute("field"))=="") {
			$this->tagName = $this->getAttribute("name");
		}

		if ($this->element->getName()=="node") 
		{
			$this->tagName = $this->element['group'].'_'.$this->element['name'];
		}
		$this->initChildren();
		$this->onLoad();
	}
	
	function onLoad() {
	}

	/**
	 * Vytvoří děti
	 */	
	function initChildren() 
	{
		foreach ($this->element->children() as $ch) 
		{
			$pName = $this->cms->file->loadPart($ch['group'], $ch->getName());			
			$this->chParts[] = new $pName($ch, $this);
		}
		//print_r($this->chParts);
	}


	/**
	 * Dá jméno věci ve formu
	 * Mohlo by se zdát, že by se to dalo zajistit přes
	 * path zjištěnou z getData, ale pokud chcu ve formu mít
	 * současně i formy dalších nodeů bez kolize, je třeba takto.
	 */	
	function getFormFieldName($view)
	{ //vrací hodnotu parametru name u inputů a podobných ve formech
		$path=$view->domPath->get();
		$first=array_shift($path);
		if (count($path)>0) {
			$p=$first."[".implode("][",$path)."]";
		} else $p=$first."[_itself]";		
		return $p;
	}
	
	/*
	 * Vrátí nodeValue
	 */
	function getText($data, $view)
	{
		$value = $this->getData($data);
		$name=$this->getFormFieldName($view);
		
		$fn="get".$view->action."Text";
		if (!is_object($text = $this->$fn($view,$name,$data))) {
			return htmlSpecialChars($text);
		} else throw new cException("doprdele ".get_Class($text)." není string ($fn, ".get_Class($this).")");
	}

	/**
	 * Vrátí XPath pro získání dat z inSXML
	 */
	function getDataPath() 
	{
		$path = array();		
		$p=$this;

		//zjistíme XPath cestu
		while ($p->parent->parent!=null)
		{ 
			if ($p->physic && $p->tagName!="") {
				if ($p->tagName!='') {
					$path[] = $p->tagName;
				} else $this->cms->debugger->warning('part doesn\'t have tagName',$p);
			}
			$p = $p->parent;
		} 

		$path[]='node';
	
		return  '/'.implode('/',array_reverse($path));
	}
	
	function getData($sxml) 
	{
		
		$path = $this->getDataPath();

		$this->cms->debugger->log('gethering data from XML : '.$path,$this);		

		$el = $sxml->xpath($path);
		
		if ($el[0] instanceof SimpleXMLElement)
		if (count($el[0]->children())==0)
		{
			return (string) $el[0];
		} 
		
		return $el[0];
		 
	}
	
	function getAttr($name) 
	{
		return $this->getAttribute($name);
	}
	
	function getAttribute($name) 
	{
		return (string) $this->element[$name];
	}
	
	
	/**
	 * Vrací kus element, který se pak dá dohromady s ostatníma a prožene se XSL
	 */
	function setSXML(SimpleXMLElement $inSXML, cView $view, SimpleXMLElement $outSXML)
	{
		$this->cms->debugger->log('setting SXML', $this);
		
		$this->inSXML = $inSXML;
		$this->outSXML = $outSXML;

		/*	cesta se musí udržovat, aby při generování formu nedocházelo k bordelu
		 *	a mohlo fungovat editování více stránek v jednom formuláři
		 */		
		if ($this->tagName!='' && $this->physic) {
			$view->domPath->add($this->tagName);
		}		

		$data = null;

		//pokud jsme skutečným listem		
		if (count($this->chParts)==0 && $this->physic) 
		{
			$data = $this->getData($inSXML);
		}
		
		if ($view->doctype!='raw' || $this->physic) {
			$outSXML = $this->setElement($outSXML, $data, $view);
		}

		//	Pokud nejsme listem, nastavíme se dětmi
		foreach ($this->chParts as $part) {
			$part->setSXML($inSXML, $view, $outSXML);
		}	
		
		//	Zkrácení cesty o jeden prvek (náš)
		if ($this->tagName!='' && $this->physic) {		
			$view->domPath->shorten();
		}
	}

	function setElement(SimpleXMLElement $parent, $value, cView $view) 
	{
		if ($this->tagName=="") return $parent;
		if ($value===null) 
		{
			return $parent->addChild($this->tagName);
		} else return $parent->addChild($this->tagName, $value);
	}
	
}

class cGadget extends cPart 
{

	public $physic = false;

	function setElement(SimpleXMLElement $parent, $value, cView $view)
	{
		if ($view->mode=="frontend" && $view->action=="show" && $view->doctype!="raw") 
		{			
			return $parent->addChild($this->tagName, $this->getXHTML($view, $value, $this->inSXML, $this->outSXML));
		}		
	}

}

class cFormElement extends cPart {

	function setElement(SimpleXMLElement $elm, $value, cView $view)
	{
		if (!$this->physic && $view->action=='show') return $elm;
		
		if ($this->tagName=="") return $elm;
		$fName = "get".$view->action."text";
		
		$path = $view->domPath->get();
		$first = array_shift($path);
		
		$fieldName = $first.'['.implode('][',$path).']';
		$id = $first.'_'.implode('_',$path);
		
		$elm->addChild($this->tagName, htmlspecialchars($this->$fName($fieldName, $id, $value, $view)));
	}
	
	function getInsertText($fieldName, $id, $value, cView $view) {
		return $this->getEditText($fieldName, $id, $value, $view);
	}

	function getEditText($fieldName, $id, $value, cView $view) {
		throw new cException("je třeba naimplementovat getEditText() u ".get_class($this));
	}

	function getShowText($fieldName, $id, $value, cView $view) {
		return $value;
	}

}

?>